package com.daxia.ogmall.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.daxia.ogmall.common.PinguanType;
import com.daxia.ogmall.common.ToBeDone;
import com.daxia.ogmall.dao.BrandDAO;
import com.daxia.ogmall.dao.ProductDAO;
import com.daxia.ogmall.dao.SpecificationDAO;
import com.daxia.ogmall.dto.BrowseRecordDTO;
import com.daxia.ogmall.dto.ProductDTO;
import com.daxia.ogmall.dto.ProductPropertiesDTO;
import com.daxia.ogmall.dto.SpecificationDTO;
import com.daxia.ogmall.model.Brand;
import com.daxia.ogmall.model.Product;
import com.daxia.ogmall.model.ProductCategory;
import com.daxia.ogmall.model.Specification;
import com.daxia.ogmall.support.Page;
import com.daxia.ogmall.util.BeanMapper;

@Service
public class ProductService {
	
	@Autowired
	private ProductDAO productDAO;
	@Autowired
	private SpecificationDAO specificationDAO;
	@Autowired
	private BrandDAO brandDAO;
	@Autowired
	private SpecificationService specificationService;
	
	public List<ProductDTO> find(ProductDTO query, Page page) {
		List<Product> models = productDAO.find(query, page);
		List<ProductDTO> dtos = toDTOs(models);
		return dtos;
	}
	
	public List<ProductDTO> findByBrowse(BrowseRecordDTO query, Page page) {  //根据浏览记录拿出浏览商品
		List<Product> models = productDAO.findByBrowsedProduct(query, page);
		List<ProductDTO> dtos = toDTOs(models);
		return dtos;
	}
	
	public List<ProductDTO> findAll() {
		return this.find(new ProductDTO(), null);
	}
	
	public List<ProductDTO> find(int count) {
		Page page = new Page();
		page.setPage(1);
		page.setPageSize(count);
		return this.find(new ProductDTO(), page);
	}
	
	public Long create(ProductDTO dto) {
		Product model = new Product();
		toModel(model, dto);
		Long id = productDAO.create(model);
		Product product = new Product();
		product.setId(id);
		if (CollectionUtils.isNotEmpty(dto.getSpecifications())) {
			for (Specification s : dto.getSpecifications()) {
				Specification m = new Specification();
				BeanMapper.copy(s, m);
				m.setProduct(product);
				specificationDAO.create(m);
			}
		}
		return id;
	}
	
	public ProductDTO load(Long id) {
	    Product model = productDAO.load(id);
	    return toDTO(model);
    }

	public void updateAllFields(ProductDTO dto) {
		Product model = productDAO.load(dto.getId());
		toModel(model, dto);
		productDAO.update(model);
    }

	public void deleteByIds(Long[] ids) {
		if (ids != null) {
			for (Long id : ids) {
				// productDAO.deleteById(id);
				Product p = productDAO.load(id);
				p.setName("【删】" + p.getName());
				p.setDeleted(true);
				productDAO.update(p);
			}
		}
    }
	
	public void deleteById(Long id) {
		this.deleteByIds(new Long[] {id});
	}
	
	public void deleteByIdPhisycal(Long id) {
		productDAO.deleteByIdPhysical(id);
	}

	public ProductDTO findOne(ProductDTO query) {
		Product model = productDAO.findOne(query);
		return toDTO(model);
	}
	
	private List<ProductDTO> toDTOs(List<Product> models) {
		if (CollectionUtils.isEmpty(models)) {
			return new ArrayList<ProductDTO>(0);
		}
		List<ProductDTO> dtos = new ArrayList<ProductDTO>(models.size());
		for (Product model : models) {
	        ProductDTO dto = toDTO(model);
	        dtos.add(dto);
        }
	    return dtos;
    }
    
    public ProductDTO toDTO(Product model) {
		if (model == null) {
			return null;
		}
		ProductDTO dto = BeanMapper.map(model, ProductDTO.class);
		
		return dto;
	}
	
	private void toModel(Product model, ProductDTO dto) {
		BeanMapper.copy(dto, model);
    }
	
	@SuppressWarnings("unused")
	private List<Product> toModels(List<ProductDTO> dtos) {
		if (CollectionUtils.isEmpty(dtos)) {
			return new ArrayList<Product>(0);
		}
		List<Product> models = new ArrayList<Product>(dtos.size());
		for (ProductDTO dto : dtos) {
	        Product model = new Product();
	        toModel(model, dto);
	        models.add(model);
        }
		return models;
	}
	
	public List<ProductDTO> getProductByProperties(List<ProductPropertiesDTO> properties,ProductDTO dto,Page page) {
		List<ProductDTO> products = new Vector<ProductDTO>();
 		List idList = productDAO.getProductByProperties(properties, dto,page);
		if(idList != null && idList.size() > 0) {
			List<Product> objs = productDAO.getProductByIds(idList);
			//注意这里，由于得到的ids是经过排序的，所以查出来的东西，也必须根据传入的顺序排列
			for(Object theId:idList) { 
				Long idLong = (Long)theId;
				for (Product model : objs) {
					if(idLong.longValue() == model.getId().longValue()) {
						 ProductDTO aModel = toDTO(model);
					     products.add(aModel);
					     break;
					}
		        }
			}
		}
		return products;
	}
	
	public List<SpecificationDTO> getSpecificationByProperties(List<ProductPropertiesDTO> properties,ProductDTO dto,Page page) {
		List<SpecificationDTO> specs = new Vector<SpecificationDTO>();
 		List idList = productDAO.getDistictSpecifation(properties, dto,page);
		if(idList != null && idList.size() > 0) {
			List<Specification> objs = specificationDAO.getSpecificationByIds(idList);
			//注意这里，由于得到的ids是经过排序的，所以查出来的东西，也必须根据传入的顺序排列
			for(Object theId:idList) { 
				Long idLong = (Long)theId;
				for (Specification model : objs) {
					if(idLong.longValue() == model.getId().longValue()) {
						 SpecificationDTO aModel = specificationService.toDTO(model);
						 specs.add(aModel);
					     break;
					}
		        }
			}
		}
		return specs;
	}
	
	public List<Brand> getDistinctBrands(List<ProductPropertiesDTO> properties,ProductDTO dto) {  //查询出所有符合条件的商品的品牌信息
		List<Brand> brands = new Vector<Brand>();
		List idList = productDAO.getDistinctBrand(properties, dto);
		if(idList != null && idList.size() > 0) {
			brands = brandDAO.getBrandByIds(idList);
		}
		return brands;
	}
	
	@Transactional
	public int updateTotalSold(List<Long> proIds) {
		int updateCount = 0;
		for(Long id:proIds) {
			updateCount += productDAO.addTotalSold(id);
		}
		return updateCount;
	}
	
	public ProductDTO findByTag(PinguanType type) {
		ProductDTO q = new ProductDTO();
		q.setPinguanType(type.getValue());
		return this.findOne(q);
	}

	public List<ProductDTO> findByCategory(ProductCategory productCategory, Page page) {
		ProductDTO query = new ProductDTO();
		query.setProductCategory(new ProductCategory());
		query.getProductCategory().setId(productCategory.getId());
		return this.find(query, page);
	}

	@ToBeDone
	public List<ProductDTO> recProducts(ProductDTO p, Page page) {
		return this.find(p, page);
	}

	@ToBeDone
	public List<ProductDTO> sameBrandProducts(ProductDTO p, Page page) {
		return this.find(new ProductDTO(), page);
	}

	@ToBeDone
	public List<ProductDTO> sameCategoryProducts(ProductDTO p, Page page) {
		return this.find(new ProductDTO(), page);
	}

	@Transactional
	public void updateStatus(Long[] ids, int status) {
		for (Long id : ids) {
			Product p = productDAO.load(id);
			p.setStatus(status);
			productDAO.update(p);
		}
	}
	
	@Transactional
	public void updateSellStatus(Long[] ids, int sellStatus) {
		for (Long id : ids) {
			Product p = productDAO.load(id);
			p.setSellingStatus(sellStatus);
			productDAO.update(p);
		}
	}

	public List<ProductDTO> findRandom(int count) {
		ProductDTO query = new ProductDTO();
		query.setFindByRandom(true);
		Page page = new Page();
		page.setPageSize(count);
		return this.find(query, page);
	}

	public void deleteByUserId(Long id) {
		productDAO.deleteByUserId(id);
	}

	@Transactional
	public void cleanup() {
		productDAO.cleanup();
	}
	
	public List<ProductDTO> findForOnlineDesign(ProductDTO dto, Page page) {
		return toDTOs(productDAO.findForOnlineDesign(dto, page));
	}
	
}
